package com.common.common;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.common.msg.ResultMsg;
import com.common.common.option.ColumnOption;
import com.common.common.util.ExcelIOUtil;
import com.common.common.util.FieldFillUtil;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * 通用Service实现
 * @param <M> dao
 * @param <T> 实体类
 *
 * @author liujun
 * @date 2024/10/10
 */
public class CommonServiceImpl<M extends BaseMapper<T>, T, K extends Serializable> extends ServiceImpl<M, T> implements CommonService<T, K> {

    public M getDao() {
        return getBaseMapper();
    }

    /**
     * 保存前校验
     *
     * @param entity 实体
     */
    @Override
    public ResultMsg<Void> saveCheckMsg(T entity) {
        return entity != null ? ResultMsg.success("保存校验通过") : ResultMsg.error("数据不能为空");
    }

    /**
     * 保存
     * @param entity 实体对象
     * @return 是否成功
     */
    @Override
    public boolean save(T entity) {
        return saveMsg(entity).isSuccess();
    }

    /**
     * 保存
     *
     * @param entity 实体
     * @return 是否成功
     */
    @Override
    public ResultMsg<Void> saveMsg(T entity) {
        ResultMsg<Void> checkMsg = saveCheckMsg(entity);
        if (!checkMsg.isSuccess()) {
            return checkMsg;
        }
        FieldFillUtil.fillByInsert(entity);
        boolean save = super.save(entity);
        return save ? ResultMsg.success("保存成功") : ResultMsg.error("保存失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveBatch(Collection<T> entityList, int batchSize) {
        if (entityList == null || entityList.isEmpty()) {
            return true;
        }
        for (T entity : entityList) {
            if (!saveCheckMsg(entity).isSuccess()) {
                return false;
            }
        }
        FieldFillUtil.fillByInsert(entityList);
        return super.saveBatch(entityList, batchSize);
    }

    @Override
    public ResultMsg<Void> saveBatchMsg(Collection<T> entityList) {
        if (entityList == null || entityList.isEmpty()) {
            return ResultMsg.success(String.format("成功保存【%s】条数据", 0));
        }
        for (T entity : entityList) {
            ResultMsg<Void> checkMsg = saveCheckMsg(entity);
            if (!checkMsg.isSuccess()) {
                return checkMsg;
            }
        }
        FieldFillUtil.fillByInsert(entityList);
        boolean saveBatch = super.saveBatch(entityList);
        return saveBatch ? ResultMsg.success(String.format("成功保存【%s】条数据", entityList.size())) : ResultMsg.error("保存失败");
    }

    /**
     * 更新前校验
     *
     * @param entity 实体
     */
    @Override
    public ResultMsg<Void> updateCheckMsg(T entity) {
        return entity != null ? ResultMsg.success("更新校验通过") : ResultMsg.error("数据不能为空");
    }

    /**
     * 更新
     * @param entity 实体对象
     * @return 是否成功
     */
    @Override
    public boolean updateById(T entity) {
        return updateMsg(entity).isSuccess();
    }

    /**
     * 更新
     *
     * @param entity 实体
     * @return 是否成功
     */
    @Override
    public ResultMsg<Void> updateMsg(T entity) {
        ResultMsg<Void> checkMsg = updateCheckMsg(entity);
        if (!checkMsg.isSuccess()) {
            return checkMsg;
        }
        FieldFillUtil.fillByUpdate(entity);
        boolean update = super.updateById(entity);
        return update ? ResultMsg.success("更新成功") : ResultMsg.error("更新失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBatchById(Collection<T> entityList, int batchSize) {
        if (entityList == null || entityList.isEmpty()) {
            return true;
        }
        for (T entity : entityList) {
            if (!updateCheckMsg(entity).isSuccess()) {
                return false;
            }
        }
        FieldFillUtil.fillByUpdate(entityList);
        return super.updateBatchById(entityList, batchSize);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultMsg<Void> updateBatchByIdMsg(Collection<T> entityList) {
        if (entityList == null || entityList.isEmpty()) {
            return ResultMsg.success(String.format("成功更新【%s】条数据", 0));
        }
        for (T entity : entityList) {
            ResultMsg<Void> checkMsg = updateCheckMsg(entity);
            if (!checkMsg.isSuccess()) {
                return checkMsg;
            }
        }
        FieldFillUtil.fillByUpdate(entityList);
        boolean updateBatchById = super.updateBatchById(entityList);
        return updateBatchById ? ResultMsg.success(String.format("成功更新【%s】条数据", entityList.size())) : ResultMsg.error("更新失败");
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdate(T entity) {
        return saveOrUpdateMsg(entity).isSuccess();
    }
    
    /**
     * 保存或更新
     *
     * @param entity 实体
     * @return 是否成功
     */
    @Override
    public ResultMsg<Void> saveOrUpdateMsg(T entity) {
        if (entity == null) {
            return ResultMsg.error("数据不能为空");
        }
        TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
        if (tableInfo == null) {
            return ResultMsg.error("获取表信息失败");
        }
        String keyProperty = tableInfo.getKeyProperty();
        if (StringUtils.isBlank(keyProperty)) {
            return ResultMsg.error("获取主键信息失败");
        }
        K idVal = (K) ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty());
        return !StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById(idVal)) ? this.updateMsg(entity) : this.saveMsg(entity);
    }

    /**
     * 删除前校验
     *
     * @param entity 实体
     */
    @Override
    public ResultMsg<Void> removeCheckMsg(T entity) {
        return entity != null ? ResultMsg.success("删除校验通过") : ResultMsg.error("数据不能为空");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeById(Serializable id) {
        return removeByIdsMsg(new ArrayList<K>(){{add((K) id);}}).isSuccess();
    }
    
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        return removeByIdsMsg((Collection<K>) idList).isSuccess();
    }
    
    /**
     * 删除
     * @param ids 主键
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultMsg<Void> removeByIdsMsg(Collection<K> ids) {
        if (ids == null || ids.isEmpty()) {
            return ResultMsg.success(String.format("成功删除【%s】条数据", 0));
        }
        List<T> list = this.listByIds(ids);
        if (list == null || list.isEmpty()) {
            return ResultMsg.success(String.format("成功删除【%s】条数据", 0));
        }
        for (T entity : list) {
            ResultMsg<Void> checkMsg = removeCheckMsg(entity);
            if (!checkMsg.isSuccess()) {
                return checkMsg;
            }
        }
        boolean removed = super.removeByIds(ids);
        return removed ? ResultMsg.success(String.format("成功删除【%s】条数据", list.size())) : ResultMsg.error("删除失败");
    }
    
    @Override
    public void exportExcel(List<T> list, List<ColumnOption> columns, HttpServletResponse response, String sheet) throws IOException {
        ExcelIOUtil.exportData(list, columns, response, "export.xlsx", sheet);
    }

    @Override
    public ResultMsg<Void> importExcel(MultipartFile file, String sheet, List<ColumnOption> columns) throws IOException {
        if (columns == null || columns.isEmpty()) {
            return ResultMsg.error("导入列配置不能为空");
        }
        if (file == null) {
            return ResultMsg.error("文件不能为空");
        }
        List<T> data = ExcelIOUtil.importData(file, sheet, columns, this.entityClass);
        return saveBatchMsg(data);
    }
}
